package com.bstek.uflo.designer.convert.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.UUID;

import org.apache.commons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.bstek.uflo.command.CommandService;
import com.bstek.uflo.designer.command.QueryProcessBlobCommand;
import com.bstek.uflo.designer.convert.ConvertService;
import com.bstek.uflo.designer.deserializer.ProcessDeserializer;
import com.bstek.uflo.designer.graph.GraphService;
import com.bstek.uflo.designer.model.process.Process;
import com.bstek.uflo.designer.security.model.ProcessEntry;
import com.bstek.uflo.designer.security.service.SecurityService;
import com.bstek.uflo.designer.serializer.ProcessSerializer;
import com.bstek.uflo.designer.utils.FileUtils;
import com.bstek.uflo.model.Blob;

/**
 * @author matt.yao@bstek.com
 * @since 1.0
 */
@Service(ConvertService.BEAN_ID)
public class ConvertServiceImpl implements ConvertService {

	@Autowired
	@Qualifier(ProcessSerializer.BEAN_ID)
	private ProcessSerializer processSerializer;

	@Autowired
	@Qualifier(ProcessDeserializer.BEAN_ID)
	private ProcessDeserializer processDeserializer;

	@Autowired
	@Qualifier(GraphService.BEAN_ID)
	private GraphService graphService;

	@Autowired
	@Qualifier(SecurityService.BEAN_ID)
	private SecurityService securityService;

	@Autowired
	@Qualifier(CommandService.BEAN_ID)
	private CommandService commandService;

	public Process graphToModel(String graphData) throws Exception {
		Document doc = DocumentHelper.parseText(graphData);
		Process process = graphService.serializer(doc);
		return process;
	}

	public File modelToUflo(Process process) throws Exception {
		Document document = processSerializer.execute(process);
		String tempFileName = UUID.randomUUID().toString() + ".uflo.xml";
		File file = new File(FileUtils.getTempDirectory(), tempFileName);
		FileOutputStream out = new FileOutputStream(file);
		OutputFormat outputFormat = OutputFormat.createPrettyPrint();
		XMLWriter xmlWriter = new XMLWriter(out, outputFormat);
		try {
			xmlWriter.write(document);
		} finally {
			out.close();
			xmlWriter.close();
		}
		return file;
	}

	public Process ufloToModel(String ufloXmlData) throws Exception {
		Document document = DocumentHelper.parseText(ufloXmlData);
		return processDeserializer.execute(document);
	}

	public Process ufloToModel(String ufloXmlData, long processId) throws Exception {
		Process process = this.ufloToModel(ufloXmlData);
		String username = securityService.getLoginUsername();
		ProcessEntry processEntry = null;
		if (StringUtils.hasText(username)) {
			processEntry = securityService.checkProcessSecurity(processId, username);
		}
		process.setProcessEntry(processEntry);
		return process;
	}

	public String modelToGraph(Process process) throws Exception {
		Document document = graphService.deserializer(process);
		String tempFileName = UUID.randomUUID().toString() + ".xml";
		OutputFormat outputFormat = OutputFormat.createCompactFormat();
		XMLWriter xmlWriter = null;
		FileOutputStream out = null;
		FileInputStream input = null;
		try {
			out = new FileOutputStream(new File(FileUtils.getTempDirectory(), tempFileName));
			xmlWriter = new XMLWriter(out, outputFormat);
			xmlWriter.write(document);
			input = new FileInputStream(new File(FileUtils.getTempDirectory(), tempFileName));
			String graphXmlData = IOUtils.toString(input, "UTF-8");
			return graphXmlData;
		} finally {
			if (out != null) {
				out.close();
			}
			if (xmlWriter != null) {
				xmlWriter.close();
			}
			if (input != null) {
				input.close();
			}
		}
	}

	public String findProcessDefinitionXml(long processId) throws Exception {
		Blob blob = commandService.executeCommand(new QueryProcessBlobCommand(processId));
		if (blob == null) {
			throw new IllegalArgumentException("流程id[" + processId + "]不合法,不存在此流程！");
		}
		byte[] blobValue = blob.getBlobValue();
		String ufloXmlData = new String(blobValue, "UTF-8");
		return ufloXmlData;
	}

}
